package com.rpc.learn.transport.handler;

import com.rpc.learn.serialize.KryoSerializer;
import com.rpc.learn.serialize.Serializer;
import com.rpc.learn.serialize.SerializerFactory;
import com.rpc.learn.transport.dto.RpcRequest;
import com.rpc.learn.transport.dto.RpcResponse;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class CustomObjectDecoder extends LengthFieldBasedFrameDecoder {

    public CustomObjectDecoder() {
        this(8*1028*1024,0,4, -4, 0);
    }

    public CustomObjectDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) {
        super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        Object decode = super.decode(ctx, in);
        if(decode instanceof ByteBuf) {
            ByteBuf frame = (ByteBuf) decode;
            if (frame.readableBytes() >= 5) {
                try {
                    return decodeFrame(frame);
                } catch (Exception e) {
                    log.error("Decode frame error!", e);
                    throw e;
                } finally {
                    frame.release();
                }
            }
        }
        return decode;
    }

    private Object decodeFrame(ByteBuf frame) {
        int fullLength = frame.readInt();
        byte msgType = frame.readByte();
        int dataLength = fullLength - 4 - 1;
        if(dataLength == 0) {
            return null;
        }
        byte[] bs = new byte[dataLength];   //实际数据的长度 - 头长度
        frame.readBytes(bs);
        Serializer serializer = SerializerFactory.getSerializer();
        if (msgType == (byte)1) {
            RpcRequest request = serializer.deserialize(bs, RpcRequest.class);
            return request;
        }
        if (msgType == (byte)2) {
            RpcResponse response = serializer.deserialize(bs, RpcResponse.class);
            return response;
        }
        return null;
    }
}
